// 采样频率
const STANDARD_FREQUENCIES_50 = [
  20.0, 23.13, 26.75, 30.93, 35.77, 41.37, 47.85, 55.34, 64.01, 74.03, 85.61,
  99.01, 114.51, 132.45, 153.21, 177.21, 205.0, 237.14, 274.28, 317.28, 367.03,
  424.54, 491.09, 568.0, 657.01, 760.0, 879.0, 1016.57, 1175.77, 1360.0,
  1573.14, 1819.43, 2104.76, 2434.67, 2816.0, 3257.14, 3767.86, 4358.29,
  5041.43, 5831.57, 6745.71, 7802.86, 9024.0, 10438.86, 12073.71, 13964.57,
  16153.14, 18689.14, 20000.0,
];

/**
 * @description 根据线性插值，计算某个频率下的分贝
 */
function linearInterpolationValue(
  point1: (number | string)[] | undefined,
  point2: (number | string)[] | undefined,
  x: number,
): number {
  if (!point1 || !point2) return Number.MAX_SAFE_INTEGER;

  if (!point1) {
    return Number(point2[1]);
  }

  if (!point2) {
    return Number(point1[1]);
  }

  const x1 = Number(point1[0]);
  const y1 = Number(point1[1]);
  const x2 = Number(point2[0]);
  const y2 = Number(point2[1]);

  const k = (y2 - y1) / (x2 - x1);
  const b = y1 - k * x1;

  return k * x + b;
}

/**
 * @description 计算每条曲线，按照采样点的的向量得分
 */
export function scoreCurveVector(points: (number | string)[][]) {
  return STANDARD_FREQUENCIES_50.map((freq) => {
    // 二分法找到对应频率中，曲线对应的分贝
    let i = 0,
      j = points.length - 1;

    while (i <= j) {
      const mid = (i + j) >> 1;

      if (!points[mid]) {
        return Number.MAX_SAFE_INTEGER;
      }

      const x = Number(points[mid][0]);
      const y = Number(points[mid][1]);

      if (x === freq) {
        return y;
      }

      if (x < freq) {
        i = mid + 1;
      } else {
        j = mid - 1;
      }
    }

    return linearInterpolationValue(points[i], points[j], freq);
  });
}

/**
 * 计算两个数值数组之间的欧氏距离
 */
export function euclideanDistance(vector1: number[], vector2: number[]) {
  if (!Array.isArray(vector1) || !Array.isArray(vector2)) {
    return Number.MAX_SAFE_INTEGER;
  }

  if (vector1.length !== vector2.length) {
    return Number.MAX_SAFE_INTEGER;
  }

  if (vector1.length === 0) {
    return 0;
  }

  let sumOfSquares = 0;
  for (let i = 0; i < vector1.length; i++) {
    const val1 = vector1[i];
    const val2 = vector2[i];

    if (Number.isNaN(val1) || Number.isNaN(val2)) {
      sumOfSquares += Number.MAX_SAFE_INTEGER;
    } else {
      const difference = val1 - val2;
      sumOfSquares += difference * difference;
    }
  }

  return Math.sqrt(sumOfSquares);
}
